package com.echat.elocation.service;

import android.Manifest;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;

import com.echat.elocation.R;
import com.echat.elocation.activity.MainActivity;
import com.echat.elocation.base.BaseActivity;
import com.echat.elocation.connect.NettyClient;
import com.echat.elocation.constant.ProtocolConstant;
import com.echat.elocation.event.HeartbeatEvent;
import com.echat.elocation.event.LocationEvent;
import com.echat.elocation.event.ConnectionEvent;
import com.echat.elocation.event.NetworkEvent;
import com.echat.elocation.event.UserInfo;
import com.echat.elocation.manager.UserInfoManager;
import com.echat.elocation.protocol.IServerReceive;
import com.echat.elocation.protocol.TerminalRequest;
import com.echat.elocation.protocol.entity.receive.RegisterRespMsg;
import com.echat.elocation.protocol.entity.receive.ServerCommonRespMsg;
import com.echat.elocation.protocol.entity.receive.TextMsgIssuedRespMsg;
import com.echat.elocation.receiver.NetworkReceiver;
import com.echat.elocation.speech.BaiduSpeech;
import com.echat.elocation.util.GpsUtils;
import com.echat.elocation.util.Logger;
import com.echat.elocation.util.ToastUtils;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author lihao
 *
 * @date 2018/7/11 9:30
 */
public class TerminalService extends Service implements IServerReceive {

    private static final String TAG = "TerminalService";

    public static final int SERVICE_ID = 100;

    private String mHost;
    private int mPort;
    private long mMinTime;

    private TerminalRequest mTerminalRequest;
    private String mAuthCode;

    private BaiduSpeech mSpeech;

    private NetworkReceiver mNetworkReceiver;
    private PowerManager.WakeLock wakeLock = null;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        acquireWakeLock();
        EventBus.getDefault().register(this);
        registerNetworkChangeReceiver();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Handler mHandler = new Handler();
        mSpeech = new BaiduSpeech(this, mHandler);
        connect();
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        releaseWakeLock();
        stopLocation();
        mSpeech.release();
        NettyClient.getInstance().close();
        unregisterNetworkChangeReceiver(mNetworkReceiver);
        EventBus.getDefault().unregister(this);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onNetworkChange(NetworkEvent event) {
        if (event.isEnable()) {
            connect();
        } else {
            NettyClient.getInstance().disconnect();
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onConnectChange(ConnectionEvent event) {
        switch (event.getState()) {
            case ConnectionEvent.CONNECT_SUCCESS:
                ToastUtils.showShort(getApplicationContext(), R.string.connect_success);
                mTerminalRequest.onTerminalRegister();
                break;
            case ConnectionEvent.CONNECT_FAIL:
                Logger.w(TAG, "onConnectChange: fail");
                ToastUtils.showShort(getApplicationContext(), R.string.connect_fail_message);
                break;
            case ConnectionEvent.CONNECT_CLOSED:
                ToastUtils.showShort(this, R.string.connect_closed);
                mAuthCode = null;
                break;
            default:
                break;
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onSendHeart(HeartbeatEvent event) {
        switch (event.getState()) {
            case WRITER_IDLE:
                if (mAuthCode != null) {
                    mTerminalRequest.onHeartbeat();
                }
            default:
                break;
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    @Override
    public void onRegisterResult(RegisterRespMsg event) {
        switch (event.getReplyCode()) {
            case RegisterRespMsg.SUCCESS:
                mAuthCode = event.getReplyToken();
                mTerminalRequest.onTerminalAuth(mAuthCode);
                break;
            case RegisterRespMsg.CAR_ALREADY_REGISTERED:
                ToastUtils.showShort(getApplicationContext(), R.string.register_car_already_registered);
                break;
            case RegisterRespMsg.CAR_NOT_FOUND:
                ToastUtils.showShort(getApplicationContext(), R.string.register_car_not_fount);
                break;
            case RegisterRespMsg.TERMINAL_ALREADY_REGISTERED:
                ToastUtils.showShort(getApplicationContext(), R.string.register_terminal_already_registered);
                break;
            case RegisterRespMsg.TERMINAL_NOT_FOUND:
                ToastUtils.showShort(getApplicationContext(), R.string.register_terminal_not_fount);
                break;
            default:
                break;
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    @Override
    public void onTextMsgIssuedResult(TextMsgIssuedRespMsg event) {
        Logger.i(TAG, "语音播报信息：" + event.getTextMsg());
        mSpeech.speak(event.getTextMsg());
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    @Override
    public void onServerCommonResult(ServerCommonRespMsg event) {
        switch (event.getReplyId()) {
            case ProtocolConstant.msg_id_terminal_authentication:
                authResult(event.getReplyCode());
                break;
            default:
                break;
        }
    }

    /**
     * 鉴权结果
     * @param result
     */
    private void authResult(int result) {
        switch (result) {
            case ServerCommonRespMsg.SUCCESS:
                ToastUtils.showShort(getApplicationContext(), R.string.auth_success);
                startLocation();
                return;
            case ServerCommonRespMsg.FAILURE:
                ToastUtils.showLong(getApplicationContext(), R.string.auth_fail);
                break;
            case ServerCommonRespMsg.MSG_ERROR:
                ToastUtils.showLong(getApplicationContext(), R.string.msg_error);
                break;
            case ServerCommonRespMsg.UNSUPPORTED:
                ToastUtils.showLong(getApplicationContext(), R.string.unsupported);
                break;
            case ServerCommonRespMsg.WARNING_MSG_ACK:
                break;
            default:
                break;
        }
        mAuthCode = null;
    }

    /**
     * 获取电源锁，保持该服务在屏幕熄灭时仍然获取CPU时，保持运行
     */
    private void acquireWakeLock(){
        if(null == wakeLock){
            PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
            if(pm != null){
                wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "TerminalService");
                if(null != wakeLock){
                    /*10 minutes*/
                    wakeLock.acquire(10*60*1000L);
                }
            }
        }
    }

    /**
     * 释放电源锁
     */
    private void releaseWakeLock(){
        if(null != wakeLock){
            wakeLock.release();
            wakeLock = null;
        }
    }

    private void registerNetworkChangeReceiver(){
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        mNetworkReceiver = new NetworkReceiver();
        registerReceiver(mNetworkReceiver, filter);
    }

    private void unregisterNetworkChangeReceiver(BroadcastReceiver receiver){
        unregisterReceiver(receiver);
    }

    public void connect(){
        if(checkConfig()){
            initInfo();
            checkGps();
            if(checkNetwork()){
                if(!NettyClient.getInstance().isConnect()){
                    NettyClient.getInstance().connect(mHost, mPort);
                }
            }
        }
    }

    private boolean checkConfig(){
        boolean isConfig = UserInfoManager.isSave(this);
        if(!isConfig){
            ToastUtils.showShort(getApplicationContext(), "未配置信息");
        }
        return isConfig;
    }

    private void checkGps(){
        if(!GpsUtils.isOpenGps()){
            ToastUtils.showLong(getApplicationContext(), "GPS未开启");
        }
    }

    private boolean checkNetwork(){
        boolean isEnable = mNetworkReceiver.isNetworkConnected(this);
        if(!isEnable){
            ToastUtils.showShort(getApplicationContext(), "网络未连接");
        }
        return isEnable;
    }

    private void initInfo() {
        UserInfo info = UserInfoManager.getUserInfo(this);
        mHost = info.getHost();
        mPort = info.getPort();
        mMinTime = info.getMinTime() * 1000;
        mTerminalRequest = new TerminalRequest(info);
    }

    private void startLocation() {
        int mMinDistance = 0;
        GpsUtils.startLocation(LocationManager.GPS_PROVIDER, mMinTime, mMinDistance, mLocationListener);
    }

    private void stopLocation() {
        GpsUtils.stopLocation(mLocationListener);
    }

    LocationListener mLocationListener = new LocationListener() {

        LocationEvent event;

        @Override
        public void onLocationChanged(Location location) {
            event = new LocationEvent();
            event.setLongitude(location.getLongitude());
            event.setLatitude(location.getLatitude());
            event.setGpsTime(location.getTime());
            event.setSpeed(location.getSpeed());
            event.setBearing(location.getBearing());
            event.setAccuracy(location.getAccuracy());
            event.setProvider(location.getProvider());
            event.setNumSatellite(numSatelliteList.size());
            EventBus.getDefault().post(event);
            if(location.getSpeed() > 0){
                mTerminalRequest.onLocationUpload(location);
            }
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };

    /**
     * 搜索到的卫星数量
     */
    private List<GpsSatellite> numSatelliteList = new ArrayList<>();

    GpsStatus.Listener gpsListener = new GpsStatus.Listener() {
        @Override
        public void onGpsStatusChanged(int event) {
            if (ActivityCompat.checkSelfPermission(TerminalService.this,
                    Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            GpsStatus status = GpsUtils.getLocationManager().getGpsStatus(null);
            updateGpsStatus(event, status);
        }
    };

    private void updateGpsStatus(int event, GpsStatus status) {
        if(event == GpsStatus.GPS_EVENT_SATELLITE_STATUS){
            int maxSatellites = status.getMaxSatellites();
            Iterator<GpsSatellite> it = status.getSatellites().iterator();
            numSatelliteList.clear();
            int count = 0;
            while (it.hasNext() && count <= maxSatellites) {
                GpsSatellite s = it.next();
                numSatelliteList.add(s);
                count++;
            }
        }
    }

}
